﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using ScrumTable.Common.Collections;

#endregion
namespace ScrumTable.UI.ViewModel.Extension
{
    /// <summary>
    /// Contains the global utilities for the URI class.
    /// </summary>
    public static class ObservableCollectionExtensions
    {
        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------


        /// <summary>
        /// Sorts the specified collection.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TKey">The type of the key.</typeparam>
        /// <param name="collection">The collection.</param>
        /// <param name="orderBy">The x2.</param>
        public static void Sort<T, TKey>(this ObservableCollection<T> collection, Func<T, TKey> orderBy)
        {
            Sort(collection, orderBy, false);
        }

        /// <summary>
        /// Sorts the specified collection.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TKey">The type of the key.</typeparam>
        /// <param name="collection">The collection.</param>
        /// <param name="orderBy">The x2.</param>
        /// <param name="isDesc">sorting in desc.</param>
        /// <param name="orderByThen">if the orderby has equal elements it use orderByThen</param>
        public static void Sort<T, TKey>(this ObservableCollection<T> collection, Func<T, TKey> orderBy, bool isDesc, Func<T, object> orderByThen=null)
        {
            List<T> sorted;
            if (isDesc)
            {
                //sorted = collection.OrderByDescending(orderBy).ToList();
                var toSort = collection.OrderByDescending(orderBy);
                if( orderByThen != null)
                {
                    toSort = toSort.OrderByDescending(orderBy).ThenBy(orderByThen);
                }
                sorted = toSort.ToList();
            }
            else
            {
                var toSort = collection.OrderBy(orderBy);

                if (orderByThen != null)
                {
                    toSort = toSort.OrderBy(orderBy).ThenBy(orderByThen);
                } 
                sorted = toSort.ToList();
            }
            for (int i = 0; i < sorted.Count(); i++)
            {
                int index = collection.IndexOf(sorted[i]);
                collection.Move(index, i);
            }
        }

       

        /// <summary>
        /// Moves all items from right to left: 
        ///<example>
        /// Example:  
        /// left   A, B, C
        /// right  A,    C , D
        /// result:
        /// left = A,    C , D
        /// </example>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="left"></param>
        /// <param name="right"></param>
        public static void UnionToLeft<T>(this IList<T> left, IList<T> right)
        {
            Dictionary<T, int> rightDictionary = new Dictionary<T, int>(right.Count);
            right.ForEachIndex(x => rightDictionary[right[x]] = x);

            
            //delete removed items)
            for (int i = left.Count - 1; i >= 0; i--)
            {
                if (!rightDictionary.ContainsKey(left[i]))
                {
                    left.RemoveAt(i);
                }
            }


            Dictionary<T, int> leftDictionary = new Dictionary<T, int>(left.Count);
            left.ForEachIndex(x => leftDictionary[left[x]] = x);

            //add new items
            for (int i = 0; i < right.Count; i++)
            {
                if (!leftDictionary.ContainsKey(right[i]))
                {
                    left.Add(right[i]);
                }
            }
        }
        #endregion
    }
}